#include "niv2.h"
#include "main.h"

extern int nbTotalPaquets;

void print(u_char *user , const struct pcap_pkthdr *h, const u_char *buff)
{
    (void)h;
    Stats* stats = (Stats*)user;
    int protocol_eth;
    const struct ether_header* eth = (const struct ether_header*)buff;

    nbTotalPaquets++;

    char temp1[100],temp2[100];
    char addr_source[18];
    char addr_dest[18];
    sprintf(addr_source,"%s",ether_ntoa((const struct ether_addr*)eth->ether_shost));
    sprintf(temp1,"ETH : de  %s ",addr_source);
    sprintf(addr_dest,"%s",ether_ntoa((const struct ether_addr*)eth->ether_dhost));
    sprintf(temp2,"à %s\n",addr_dest);
    char temp[200];
    strcpy(temp,temp1);
    strcat(temp,temp2);
    printD(temp);

    struct ethernet_addr * eth_addr = stats->eth;
    bool found_src = false;
    bool found_dest = false;
    while ( (!found_src || !found_dest) && eth_addr != NULL) 
    {
        if (strcmp(eth_addr->addr,addr_source)==0)
        {
            found_src = true;
        }
        if (strcmp(eth_addr->addr,addr_dest)==0)
        {
            found_dest = true;
        }
        eth_addr = eth_addr->next;
    }

    if (!found_src)
    {
        struct ethernet_addr * ajout;
        ajout = (struct ethernet_addr *)malloc(sizeof(struct ethernet_addr));
        strcpy( ajout->addr, addr_source);
        ajout->next = NULL;
        eth_addr = stats->eth;
        if (eth_addr == NULL)
        {
            stats->eth = ajout;
        } else 
        {
            while (eth_addr->next != NULL)
            {
                eth_addr = eth_addr->next;
            }
            eth_addr->next = ajout;
        } 

    }
    if (!found_dest && strcmp(addr_source,addr_dest)!=0)
    {
        struct ethernet_addr * ajout;
        ajout = (struct ethernet_addr *)malloc(sizeof(struct ethernet_addr));
        strcpy( ajout->addr, addr_dest);
        ajout->next = NULL;
        eth_addr = stats->eth;
        if (eth_addr == NULL)
        {
            stats->eth = ajout;
        } else 
        {
            while (eth_addr->next != NULL)
            {
                eth_addr = eth_addr->next;
            }
            eth_addr->next = ajout;
        } 

    }

    char temp000[200];

    //Prochain entete
    protocol_eth = htons(eth->ether_type);
    if (protocol_eth<=1500)
    {
        printD("LLC\n"); 
    } else 
    {  
        switch (protocol_eth) 
        {
            case ETHERTYPE_LOOPBACK: printD("Loopback packet\n"); break;
            case ETHERTYPE_IP: printIP(buff+ETH_HLEN,stats); break;
            case ETHERTYPE_ARP: printARP(buff+ETH_HLEN); break;
            case ETHERTYPE_REVARP: printD("RARP\n"); break;
            case ETHERTYPE_IPX: printD("IPX\n"); break;
            case ETHERTYPE_IPV6: printIPV6(buff+ETH_HLEN,stats); break;
            case ETHERTYPE_PUP : printD("PUP\n");break;
            case ETHERTYPE_EAP : printD("EAP\n");break;
            default : 
                                 sprintf(temp000,"Inconnu %x\n",protocol_eth);
                                 printD(temp000);
        }
    }
}

void printARP(const u_char* buff)
{
    const struct arphdr2 *arp_hdr = (const struct arphdr2*)buff;
    const unsigned char * ip;

    char temp[200];
    strcpy(temp,"ARP : ");
    char temp1[200],temp2[100];

    switch ((arp_hdr->ar_op)>>8)
    {
        case ARPOP_REQUEST:  
            ip = arp_hdr->__ar_tip;
            sprintf(temp1,"Qui a %d.%d.%d.%d ? ",ip[0],ip[1],ip[2],ip[3]);
            ip = arp_hdr->__ar_sip;
            sprintf(temp2,"Dites le à %d.%d.%d.%d\n",ip[0],ip[1],ip[2],ip[3]);
            strcat(temp1,temp2);
            break;
        case ARPOP_REPLY: 
            ip = arp_hdr->__ar_sip;
            sprintf(temp1,"J'ai %d.%d.%d.%d.\n",ip[0],ip[1],ip[2],ip[3]);
            break;
    }
    strcat(temp,temp1);
    printD(temp);
}
